﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;


namespace EChartsApp
{
    public class EChartsConverter : JsonConverter
    {

        public static WUDI.ECharts.EChartsOption option_Obj = Activator.CreateInstance(typeof(WUDI.ECharts.EChartsOption)) as WUDI.ECharts.EChartsOption;

        #region 初始化 所有类级别的属性值
        static EChartsConverter()
        {
            InitPropValue(option_Obj);
        }

        private static void InitPropValue(object default_Obj)
        {
            var objType = default_Obj.GetType();
            var props = objType.GetProperties().Where(t => !IsSimpleType(t.PropertyType)).ToList();
            foreach (PropertyInfo prop in props)
            {
                var obj = Activator.CreateInstance(prop.PropertyType);
                prop.SetValue(default_Obj, obj);
                InitPropValue(obj);
            }
        }

        private static bool IsSimpleType(System.Type type)
        {
            System.Type t = Nullable.GetUnderlyingType(type) ?? type;
            if (t.IsPrimitive
                || t.IsEnum
                || t == typeof(string)
                || t.IsAssignableFrom(typeof(Guid))
                || t.IsAssignableFrom(typeof(DateTime))
                || t.IsArray
                || t.IsGenericType
                ) return true;
            return false;
        } 
        #endregion


        private readonly JObject JObj_ECharts = null;

        public EChartsConverter(List<object> series)
        {
            if (series.Any())
            {
                var serieType = series?.FirstOrDefault()?.GetType();
                if (serieType != null)
                {
                    var lst = new List<object>(series.Count);
                    for (int j = 0; j < series.Count; j++)
                    {
                        var serie = Activator.CreateInstance(serieType);

                        //初始化 类级别 属性值，如：Bar => markLine => LineStyle
                        InitPropValue(serie);

                        lst.Add(serie);
                    }
                    option_Obj.series = lst;
                }
            }

            JsonSerializer serializer = new JsonSerializer();
            serializer.Converters.Add(new StringEnumConverter());
            JObj_ECharts = JObject.FromObject(option_Obj, serializer);
        }

        /// <summary>
        /// 需要检查(默认属性值与对象属性值相同)
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static bool NeedCheck(System.Type type)
        {
            System.Type t = Nullable.GetUnderlyingType(type) ?? type;
            if (t.IsPrimitive
                || t.IsEnum
                || t == typeof(string)
                || t.IsAssignableFrom(typeof(Guid))
                || t.IsAssignableFrom(typeof(DateTime))
                ) return true;
            return false;
        }


        /// <summary>
        /// 是否允许转换
        /// </summary>
        public override bool CanConvert(Type objectType)
        {
            Console.WriteLine(objectType.FullName);

            return NeedCheck(objectType);
        }


        /// <summary>
        /// 是否允许转换JSON字符串时调用
        /// </summary>
        public override bool CanWrite
        {
            get
            {
                return true;
            }
        }


        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return existingValue;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            Console.WriteLine("\t\t" + "$." + writer.Path);

            //防止枚举序列化成 数字
            value = value.GetType().IsEnum ? value.ToString() : value;

            var nodes = writer.Path.Split('.');

            var prop_name = nodes.Last();

            var str_value = (value ?? string.Empty).ToString();

            var default_value = JObj_ECharts.SelectToken("$." + writer.Path)?.Value<string>();

            var lst = new List<string>()
            {
                "animationThreshold","precision","animation","animationDuration"
            };

            if (lst.Contains(prop_name))
            {

            }

            if (nodes.Contains("markLine"))
            {

            }


            if (prop_name.Equals("type"))
            {
                writer.WriteValue(value);
            }
            //默认属性值与对象属性值相同,暂时一律设定空值
            else if (str_value.Equals(default_value, StringComparison.OrdinalIgnoreCase))
            {
                writer.WriteNull();
            }
            else
            {
                writer.WriteValue(value);
            }
        }



    }
}
